import ECI20180808, * as $ECI20180808 from '@alicloud/eci20180808';
import OpenApi, * as $OpenApi from '@alicloud/openapi-client';

export enum VolumeType {
  EmptyDir = 'EmptyDir',
  NFSVolume = 'NFSVolume',
  ConfigFileVolume = 'ConfigFileVolume',
}

export enum SpotStrategy {
  NoSpot = 'NoSpot',
  SpotWithPriceLimit = 'SpotWithPriceLimit',
  SpotAsPriceGo = 'SpotAsPriceGo',
}

export interface ContainerConfig {
  name: string;
  image: string;
  memory: number; // GB
  cpu: number; // cores
  commands?: string[];
  args?: string[];
  environmentVar?: Record<string, string>;
  volumeMount?: VolumeMount[];
  ports?: ContainerPort[];
}

export interface VolumeMount {
  name: string;
  mountPath: string;
  readOnly?: boolean;
}

export interface ContainerPort {
  protocol: 'TCP' | 'UDP';
  port: number;
}

export interface ContainerGroupConfig {
  containerGroupName: string;
  regionId: string;
  vSwitchId: string;
  securityGroupId: string;
  computeCategory?: string[];
  container: ContainerConfig[];
  volume?: Volume[];
  restartPolicy?: 'Always' | 'Never' | 'OnFailure';
  autoMatchImageCache?: boolean;
  eipInstanceId?: string;
  autoCreateEip?: boolean;
  spotStrategy?: SpotStrategy;
  spotDuration?: number;
  instanceType?: string;
}

export interface Volume {
  name: string;
  type: VolumeType;
  NFSVolume?: {
    server: string;
    path: string;
    readOnly: boolean;
  };
  configFileVolume?: {
    configFileToPaths: Array<{
      content: string;
      path: string;
    }>;
  };
}

export class EciManager {
  private client: ECI20180808.default;
  private defaultRegionId: string;

  constructor(accessKeyId: string, accessKeySecret: string, regionId: string) {
    const config = new $OpenApi.Config({
      accessKeyId,
      accessKeySecret,
      regionId,
    });
    config.endpoint = `eci.${regionId}.aliyuncs.com`;
    this.client = new ECI20180808.default(config);
    this.defaultRegionId = regionId;
  }

  async createContainerGroup(config: ContainerGroupConfig): Promise<string> {
    const createContainerGroupRequest = new $ECI20180808.CreateContainerGroupRequest({
      containerGroupName: config.containerGroupName,
      regionId: config.regionId || this.defaultRegionId,
      vSwitchId: config.vSwitchId,
      securityGroupId: config.securityGroupId,
      computeCategory: config.computeCategory,
      spotStrategy: config.spotStrategy,
      spotDuration: config.spotDuration,
      instanceType: config.instanceType,
      container: config.container.map(container => ({
        name: container.name,
        image: container.image,
        memory: container.memory,
        cpu: container.cpu,
        command: container.commands,
        args: container.args,
        environmentVar: container.environmentVar ? Object.entries(container.environmentVar).map(([key, value]) => ({
          key,
          value,
        })) : undefined,
        volumeMount: container.volumeMount?.map(mount => ({
          name: mount.name,
          mountPath: mount.mountPath,
          readOnly: mount.readOnly,
        })),
        ports: container.ports?.map(port => ({
          protocol: port.protocol,
          port: port.port,
        })),
      })),
      volume: config.volume?.map(volume => ({
        name: volume.name,
        type: volume.type,
        NFSVolume: volume.NFSVolume,
        configFileVolume: volume.configFileVolume,
      })),
      restartPolicy: config.restartPolicy,
      autoMatchImageCache: config.autoMatchImageCache,
      eipInstanceId: config.eipInstanceId,
      autoCreateEip: config.autoCreateEip,
    });

    try {
      const response = await this.client.createContainerGroup(createContainerGroupRequest);
      if (!response?.body?.containerGroupId) {
        throw new Error(`API response missing containerGroupId. Full response: ${JSON.stringify(response)}`);
      }
      return response.body.containerGroupId;
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Unknown error occurred';
      throw new Error(`Failed to create container group: ${message}`);
    }
  }

  async describeContainerGroups(containerGroupIds: string[], regionId?: string, containerGroupName?: string):Promise<ECI20180808.DescribeContainerGroupsResponseBodyContainerGroups[]> {
    const requestParams: any = {
      regionId: regionId || this.defaultRegionId,
    };
    
    if (containerGroupIds?.length > 0) {
      requestParams.containerGroupIds = containerGroupIds.join(',');
    }
    if (containerGroupName) {
      requestParams.containerGroupName = containerGroupName;
    }

    const describeContainerGroupsRequest = new $ECI20180808.DescribeContainerGroupsRequest(requestParams);

    try {
      const response = await this.client.describeContainerGroups(describeContainerGroupsRequest);
      if (!response?.body?.containerGroups) {
        throw new Error(`API response missing containerGroups. Full response: ${JSON.stringify(response)}`);
      }
      return response.body.containerGroups;
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Unknown error occurred';
      throw new Error(`Failed to describe container groups: ${message}`);
    }
  }

  async deleteContainerGroup(containerGroupId: string, regionId?: string, containerGroupName?: string): Promise<void> {
    const requestParams: any = {
      regionId: regionId || this.defaultRegionId,
    };
    
    if (containerGroupName) {
      // 先通过名称查询容器组ID
      const groups = await this.describeContainerGroups([], regionId, containerGroupName);
      if (!groups || groups.length === 0) {
        throw new Error(`Container group with name "${containerGroupName}" not found`);
      }
      requestParams.containerGroupId = groups[0].containerGroupId;
    } else {
      requestParams.containerGroupId = containerGroupId;
    }

    const deleteContainerGroupRequest = new $ECI20180808.DeleteContainerGroupRequest(requestParams);

    try {
      await this.client.deleteContainerGroup(deleteContainerGroupRequest);
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Unknown error occurred';
      throw new Error(`Failed to delete container group: ${message}`);
    }
  }

  async restartContainerGroup(containerGroupId: string, regionId?: string): Promise<void> {
    const restartContainerGroupRequest = new $ECI20180808.RestartContainerGroupRequest({
      containerGroupId,
      regionId: regionId || this.defaultRegionId,
    });

    try {
      await this.client.restartContainerGroup(restartContainerGroupRequest);
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Unknown error occurred';
      throw new Error(`Failed to restart container group: ${message}`);
    }
  }

  async describeContainerGroupEvents(
    containerGroupIds: string[],
    regionId?: string,
    options?: {
      sinceSecond?: number;
      limit?: number;
      nextToken?: string;
      eventSource?: 'EciService' | 'K8sAgent';
    }
  ): Promise<ECI20180808.DescribeContainerGroupEventsResponseBodyData[]> {
    const requestParams: any = {
      regionId: regionId || this.defaultRegionId,
      containerGroupIds: JSON.stringify(containerGroupIds),
    };

    // 添加可选参数
    if (options?.sinceSecond !== undefined) {
      requestParams.sinceSecond = options.sinceSecond;
    }
    if (options?.limit !== undefined) {
      requestParams.limit = options.limit;
    }
    if (options?.nextToken) {
      requestParams.nextToken = options.nextToken;
    }
    if (options?.eventSource) {
      requestParams.eventSource = options.eventSource;
    }

    const describeContainerGroupEventsRequest = new $ECI20180808.DescribeContainerGroupEventsRequest(requestParams);

    try {
      const response = await this.client.describeContainerGroupEvents(describeContainerGroupEventsRequest);
      if (!response?.body?.data) {
        throw new Error(`API response missing events data. Full response: ${JSON.stringify(response)}`);
      }
      return response.body.data;
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Unknown error occurred';
      throw new Error(`Failed to describe container group events: ${message}`);
    }
  }
}